#include "header.hpp"
using namespace std;

//Experiment for move constructor
//Types of constructor: 1)Normal 2)Copy 3)Move

//Formula:
//Copy Constructor:         Class(const Class& ref);
//Assign Operator:          Class& operator=(const Class& ref);
//Move Constructor:         Class(Class&& ref);
//Move Assign Operator:     Class& operator=(Class&& ref);
class Casual{
private:
    int* _pval;

public:
    //1)Normal constructor
    Casual() = default;

    Casual(int val){
        cout << "invoke normal constructor" << endl;
        _pval = new int(val);
    }

    //2)Copy constructor
    Casual(const Casual& other){
        cout << "invoke copy constructor" << endl;
        _pval = new int(*other._pval);
    }

    //3)Move constructor
    Casual(Casual&& other){
        cout << "invoke move constructor" << endl;
        _pval = other._pval;
        other._pval = nullptr;
    }

    //Destructor
    ~Casual(){
        if(_pval){
            cout << "Destroy object" << endl;
            delete _pval;
        }
    }

    //Public interface
    int Data(){
        return *_pval;
    }
};

void test3(){
    //Annotate move constructor, the result is invoke copy constructor
    //This phenomenon proves:
    //the priority of move constructor is higher than copy constructor

    Casual cas1(5);
    Casual cas2(move(cas1)); //Destroy once -> invoke move constructor
    cout << endl;

    //Create object by rval
    //※The temporary object has "const" attribute
    Casual cas3(const_cast<Casual&&>(Casual(3)));
    cout << cas3.Data() << endl;
    cout << endl;
}
